package cn.openea.perpartner.meily.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.utils.Arith;
import cn.openea.perpartner.common.core.utils.StringUtils;
import cn.openea.perpartner.meily.util.UserContext;
import cn.openea.perpartner.meily.web.entity.Article;
import cn.openea.perpartner.meily.web.entity.LearningCourse;
import cn.openea.perpartner.meily.web.entity.vo.ArticleSearchVo;
import cn.openea.perpartner.meily.web.entity.vo.ArticleVo;
import cn.openea.perpartner.meily.web.mapper.ArticleMapper;
import cn.openea.perpartner.meily.web.service.IArticleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.NonNull;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

/**
 * @author rains
 * @since 2023-06-19 14:52
 */
@Service("articleService")
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements IArticleService {


    @Override
    public List<Article> selectList(ArticleSearchVo searchVo) {
        return list(buildQueryWrapper(searchVo, true));
    }

    private LambdaQueryWrapper<Article> buildQueryWrapper(ArticleSearchVo searchVo, boolean isSort) {
        if (null == searchVo) {
            return null;
        }
        searchVo.buildDateRangeParams();
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        Short isTop = searchVo.getIsTop();
        if (isTop != null) {
            queryWrapper = isTop == (short) 0 ? queryWrapper.eq(Article::getTop, 0)
                    : queryWrapper.ne(Article::getTop, 0);
        }
        if (searchVo.getStatus() != null) {
            queryWrapper.eq(Article::getStatus, searchVo.getStatus());
        }
        if (StrUtil.isNotBlank(searchVo.getTitle())) {
            queryWrapper.like(Article::getTitle, searchVo.getTitle());
        }
        if (StrUtil.isNotBlank(searchVo.getSearchStr())) {
            queryWrapper.and(wrap -> wrap.like(Article::getTitle, searchVo.getSearchStr())
                    .or().like(Article::getContent, searchVo.getSearchStr()));
        }
        if (StringUtils.isNotBlank(searchVo.getStartDate()) && StringUtils.isNotBlank(searchVo.getEndDate())) {
            queryWrapper.apply("DATE(create_time) BETWEEN '" + searchVo.getStartDate() + "' AND '" + searchVo.getEndDate() + "'");
        }
        if (isSort) {
            queryWrapper.orderByDesc(Article::getTop);
            queryWrapper.orderByDesc(Article::getCreateTime);
        }
        return queryWrapper;
    }

    @Override
    public boolean topArticle(@NonNull Long id) {
        Optional.ofNullable(getById(id))
                .orElseThrow(() -> new ServiceException("文章不存在"));
        // 查询最上面的一个数据
        Article article = getOne(Wrappers.<Article>lambdaQuery()
                .orderByDesc(Article::getTop)
                .last("limit 1"));
        int top = 1;
        if (BeanUtil.isNotEmpty(article)) {
            top = Convert.toInt(Arith.add(article.getTop(), 1));
        }
        return updateById(Article.builder()
                .id(id)
                .top(top).build());
    }

    @Override
    public boolean cancelTop(@NonNull Long id) {
        Article oldArticle = Optional.ofNullable(getById(id))
                .orElseThrow(() -> new ServiceException("文章不存在"));
        if (oldArticle.getTop() == 0) {
            // 不用继续下去了，本来就没有置顶
            return true;
        }
        // 查询最上面的一个数据
        Article article = getOne(Wrappers.<Article>lambdaQuery()
                .orderByDesc(Article::getTop)
                .last("limit 1"));
        if (!article.getId().equals(oldArticle.getId())) {
            // 不是最上面的那个，依次减低优先级
            // 这个视频置顶优先级高的进行降级 比如 这个视频排序5，现在要取消置顶，就要有视频取代它的位置
            baseMapper.downgradeTop(oldArticle.getTop());
        }
        return updateById(Article.builder()
                .id(id)
                .top(0).build());
    }

    @Override
    public void addArticle(@NonNull ArticleVo articleVo) {
        // 判断数据存在不存在
        Article repeatArticle = findByTitle(articleVo.getTitle());
        if (repeatArticle != null) {
            throw new ServiceException("标题为" + repeatArticle.getTitle() + "的文章已存在");
        }
        Article article = new Article();
        BeanUtil.copyProperties(articleVo, article);
        article.setCreateId(UserContext.getUserId());
        save(article);
    }

    @Override
    public void updateArticle(@NonNull ArticleVo articleVo) {
        if (articleVo.getId() == null) {
            throw new ServiceException("文章不存在");
        }
        Article oldArticle = Optional.ofNullable(getById(articleVo.getId()))
                .orElseThrow(() -> new ServiceException("文章不存在"));
        Article repeatArticle = findByTitle(articleVo.getTitle());
        if (repeatArticle != null && !repeatArticle.getId().equals(oldArticle.getId())) {
            throw new ServiceException("标题为" + repeatArticle.getTitle() + "的文章已存在");
        }
        oldArticle.setTitle(articleVo.getTitle());
        oldArticle.setContent(articleVo.getContent());
        oldArticle.setImage(articleVo.getImage());
        oldArticle.setUrl(articleVo.getUrl());
        updateById(oldArticle);
    }

    @Override
    public Article findByTitle(String title) {
        if (StringUtils.isBlank(title)) {
            return null;
        }
        return baseMapper.selectOne(Wrappers.<Article>lambdaQuery()
                .eq(Article::getTitle, title)
                .last("limit 1"));
    }

    @Override
    public boolean shelfArticle(Long id) {
        Optional.ofNullable(getById(id))
                .orElseThrow(() -> new ServiceException("文章不存在"));
        return updateById(Article.builder()
                .id(id)
                .status((short) 0).build());
    }

    @Override
    public boolean downArticle(Long id) {
        Optional.ofNullable(getById(id))
                .orElseThrow(() -> new ServiceException("文章不存在"));
        return updateById(Article.builder()
                .id(id)
                .status((short) 1).build());
    }

    @Override
    public List<Article> getList(ArticleSearchVo searchVo) {
        if (null == searchVo) {
            return null;
        }

        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getStatus, 0);// 查询已上架的数据

        Short isTop = searchVo.getIsTop();
        if (isTop != null) {
            // 查询已置顶数据
            queryWrapper = isTop == (short) 1 ? queryWrapper.ne(Article::getTop, 0)
                    : queryWrapper.eq(Article::getTop, 0);
        }

        if (StrUtil.isNotBlank(searchVo.getSearchStr())) {
            queryWrapper.and(wrap -> wrap.like(Article::getTitle, searchVo.getSearchStr())
                    .or().like(Article::getContent, searchVo.getSearchStr()));
        }

        queryWrapper.orderByDesc(Article::getCreateTime);

        return list(queryWrapper);
    }
}
